package com.eastedu.superise.handler.question.handler.completion;

import com.eastedu.common.enums.MediaTypeEnum;
import com.eastedu.common.model.question.Fragment;
import com.eastedu.common.model.question.QuestionItemContent;
import com.eastedu.superise.handler.question.handler.ContentConverter;
import com.eastedu.superise.handler.question.handler.PatternConstant;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;

/**
 * Stem content converter.
 *
 * @author Administrator
 */
public class StemContentConverter implements ContentConverter {

    @Override
    public void convert(List<QuestionItemContent> contents) {
        for (QuestionItemContent itemContent : contents) {
            List<Fragment> newFragments = new ArrayList<>();
            List<Fragment> fragments = itemContent.getFragments();
            for (Fragment fragment : fragments) {
                String content = fragment.getContent();
                // 分隔内容，并保留分隔符
                String[] split = content.split(PatternConstant.SPIT_WITH_ORDER_AND_SPACE_AND_KEEP_SEPARATOR);
                for (String piece : split) {
                    if (StringUtils.isBlank(piece)) {
                        continue;
                    }
                    // 根据内容转换出分隔符，为空则为普通内容（这里是全匹配，不是find）
                    SeparateSymbol separateSymbol = SeparateSymbol.getByContent(piece);
                    BiFunction<Fragment, String, Fragment> function = separateSymbol.getFunction();
                    Fragment f1 = function.apply(fragment, piece);
                    newFragments.add(f1);

                    if (separateSymbol != SeparateSymbol.NORMAL) {
                        // 非普通内容，后面追加空字符串文本， 为了兼容前端编辑器鼠标定位问题
                        Fragment e = Fragment.copyWithoutContent(fragment, false);
                        e.setMediaType(MediaTypeEnum.TEXT);
                        e.setContent("");
                        newFragments.add(e);
                    }
                }
            }
            itemContent.setFragments(newFragments);
        }
    }

    /**
     * The enum Separate symbol.
     */
    enum SeparateSymbol {
        /**
         * 中英文括号匹配（序号）
         */
        ORDER(PatternConstant.ORDER, SeparateSymbol::createLoginFragment),
        /**
         * 8/16个空格,中英文括号、方括号（中间2个全角）
         */
        SPACE(PatternConstant.SPACE, SeparateSymbol::createBlankFragment),
        /**
         * 普通内容.
         */
        NORMAL("", SeparateSymbol::createNormalFragment);


        /**
         * 全匹配正则
         */
        private final String regEx;
        private final BiFunction<Fragment, String, Fragment> function;

        SeparateSymbol(String regEx, BiFunction<Fragment, String, Fragment> function) {
            this.regEx = regEx;
            this.function = function;
        }

        private static Fragment createFragment(Fragment fragment, String content, MediaTypeEnum mediaType) {
            Fragment f1 = Fragment.copyWithoutContent(fragment, false);
            f1.setContent(content);
            f1.setMediaType(mediaType);
            return f1;
        }

        private static Fragment createLoginFragment(Fragment fragment, String order) {
            return createFragment(fragment, order, MediaTypeEnum.LOGICAL_PARAGRAPH);
        }

        private static Fragment createBlankFragment(Fragment fragment, String space) {
            Fragment f1 = createFragment(fragment, "", MediaTypeEnum.BLANK);
            // 根据内容分析下划线样式
            String style = space.matches("[_\\s]+") ? "underline" : space.matches("\\(\\u3000+\\)") ? "enBrackets" : space.matches("（\\u3000+）") ? "cnBrackets" : space.matches("\\[\\u3000+\\]") ? "sqBrackets" : "unknown";
            f1.getStyles().add(style);
            return f1;
        }

        private static Fragment createNormalFragment(Fragment fragment, String content) {
            Fragment f1 = Fragment.copyWithoutContent(fragment, true);
            f1.setContent(content);
            return f1;
        }

        /**
         * 根据内容匹配获取枚举.
         *
         * @param content the content
         *
         * @return the by content
         */
        public static SeparateSymbol getByContent(String content) {
            for (SeparateSymbol symbol : values()) {
                if (symbol.match(content)) {
                    return symbol;
                }
            }
            return NORMAL;
        }

        /**
         * 内容是否匹配.
         *
         * @param content the content
         *
         * @return the boolean
         */
        public boolean match(String content) {
            return content.matches(this.regEx);
        }

        /**
         * Gets function.
         *
         * @return the function
         */
        public BiFunction<Fragment, String, Fragment> getFunction() {
            return function;
        }
    }


}
